<!-- 黑色科技风地图 -->
<template>
  <div id="mapbox-container">
    <button class="view-style" @click="getView">获取视角{{ zoomValue }}</button>
    <button class="view-style" style="left: 150px;" @click="changeSchool">切换校区</button>
    <div class="style-name">
      <a-button @click.stop="openFile">
        <DownloadOutlined />
        导入模型
      </a-button>
      <input ref="exportGltf" type="file" accept=".glb" hidden @change="exportModel" />
      <a-button style="margin-left: 20px" @click="exportJsonFile">
        <template #icon>
          <upload-outlined />
        </template>
        导出模型配置文件
      </a-button>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, getCurrentInstance } from 'vue'
import mapboxgl from '../../components/mapbox/mapbox.js'
import U from 'mapbox-gl-utils'
import axios from 'axios'
import api from '../../api/geoserver'
import * as turf from '@turf/turf'
// import MapboxDraw from '@mapbox/mapbox-gl-draw'
// import MapboxLanguage from '@mapbox/mapbox-gl-language'
import { Threebox, THREE } from 'threebox-plugin'
import { message } from 'ant-design-vue'
import {
  DownloadOutlined,
  UploadOutlined
} from '@ant-design/icons-vue'
import { exportJson } from '../../utils/xingutils.js'

defineProps({
  visible: {
    type: Boolean,
    default: false
  }
})
let map = null
let xiaoqu = true
let molayersData

const exportGltf = ref(null)

const zoomValue = ref('15.3')

// const emit = defineEmits(['onload'])
const { proxy } = getCurrentInstance()
const path = import.meta.env.VITE_APP_PATH

onMounted(() => {
  loadConfig()
})

// 同步加载底图配置信息
async function loadConfig() {
  const style = await axios.get(import.meta.env.VITE_APP_PATH + 'config/white-v4.json').catch((err) => console.log(err))
  console.log(style)
  initMap(style.data)
}

// 根据配置信息初始化地图
function initMap(style) {
  // 初始化创建mapbox地图 ======'name': '昆明医科大学',

  map = new mapboxgl.Map({
    container: 'mapbox-container',
    style: style,
    // style: 'mapbox://styles/mapbox/dark-v11',
    center: [102.82766155824066, 24.84689477228241],
    zoom: 15.9,
    pitch: 49.2,
    bearing: -137.7
  })
  // mapboxgl.setRTLTextPlugin(
  //   'https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-rtl-text/v0.2.3/mapbox-gl-rtl-text.js'
  // )
  // map.addControl(new MapboxLanguage({defaultLanguage: 'zh-Hans'}))
  // map.addControl(new MapboxDraw(), 'bottom-right')

  // 初始化threebox对象并加到全局环境---只能放在这，放在map创建完成后load中模型移动不生效
  window.tb = new Threebox(map, map.getCanvas().getContext('webgl'), {
    defaultLights: true,
    // realSunlight: true,
    enableSelectingFeatures: true, //模型是否可以被选择
    enableSelectingObjects: true, //模型是否可以被选中
    enableDraggingObjects: true, //模型是否可以被拖动和移动
    enableRotatingObjects: true, //模型是否可以被旋转
    enableTooltips: true // 模型是否显示标签
  })


  // 等map创建完成后加载建筑图层
  map.on('load', function () {
    // Start the animation.
    // rotateCamera(0)

    // Add 3d buildings and remove label layers to enhance the map
    // const layers = map.getStyle().layers;
    // for (let i = 0; i < layers.length; i++) {
    // console.log(layers[i]);
    // if (layers[i].type === "symbol" && layers[i].layout["text-field"]) {
    // remove text labels
    // map.removeLayer(layers[i].id)
    // }
    // }

    // 初始化mapbox工具类
    U.init(map)

    // 创建雾气
    map.setFog({
      'horizon-blend': 0.3,
      color: '#f8f0e3'
      // 'high-color': '#add8e6',
      // 'space-color': '#d8f2ff',
      // 'star-intensity': 0.0
    })
    map.loadImage('./images/road/daoluarrow.png',
      (error, image) => {
        if (error) throw error
        map.addImage('jiantou', image)
      }
    )
    setTimeout(() => {
      map.loadImage('./images/material/shuimian3.jpg',
        (error, image) => {
          if (error) throw error
          map.addImage('shuimian', image)
        }
      )
    }, 100)

    map.loadImage('./images/material/caodi.jpg',
      (error, image) => {
        if (error) throw error
        map.addImage('caodi', image)
      }
    )
    map.loadImage('./images/material/yzdm.jpg',
      (error, image) => {
        if (error) throw error
        map.addImage('yzdm', image)
      }
    )
    map.loadImage('./images/material/jiaxiao.jpg',
      (error, image) => {
        if (error) throw error
        map.addImage('jiaxiao', image)
      }
    )
    map.loadImage('./images/treeflower/heihuaishu.png',
      (error, image) => {
        if (error) throw error
        map.addImage('合欢树', image)
      }
    )
    map.loadImage('./images/treeflower/hua.png',
      (error, image) => {
        if (error) throw error
        map.addImage('花', image)
      }
    )
    map.loadImage('./images/treeflower/yangshu.png',
      (error, image) => {
        if (error) throw error
        map.addImage('杨树', image)
      }
    )
    // 抛出map创建完成事件
    // emit('onload', map)
    // loadDatas()
    // addChartletLyer()
    loadLayerJson()
  })
  map.on('click', function (e) {
    // console.log("----click----");
    // console.log(e.point);
    // console.log(e.lngLat);
  })
  map.on('dblclick', function (e) {
    // console.log("----dblclick----");
  })
  map.on('zoom', function () {
    zoomValue.value = map.getZoom().toFixed(1)
  })
}
const parameter = {
  service: 'WFS',
  version: '1.0.0',
  request: 'GetFeature',
  maxFeatures: '10000',
  outputFormat: 'application/json'
}

// 加载图层数据
async function loadDatas() {
  map.addSource('wms-test-source', {
    type: 'raster',
    // use the tiles option to specify a WMS tile source URL
    // https://docs.mapbox.com/mapbox-gl-js/style-spec/sources/
    tiles: [
      'http://39.105.214.6:8081/geoserver/gwc/service/wmts?layer=zzdx:zzdx_campusmap_baselayer&style=&tilematrixset=EPSG:900913&Service=WMTS&Request=GetTile&Version=1.0.0&Format=image/png&TileMatrix=EPSG:900913:{z}&TileCol={x}&TileRow={y}'
    ],
    tileSize: 256
  })
  map.addLayer({
    id: 'wms-test-layer',
    type: 'raster',
    source: 'wms-test-source',
    paint: {}
  })


  // parameter.typeName = 'sqsfgx:dlmc_point'
  // const roadData = await api
  //   .getLayerData('sqsfgx', parameter)
  //   .catch((err) => console.log(err))

  // map.addSource('dlmc_point', {
  //   type: 'geojson',
  //   data: roadData
  // })
  // console.log('roomData', roomData)

  // map.addSource('roomData', {
  //   type: 'geojson',
  //   data: roomData
  // })
  // map.addLayer({
  //   id: 'buildings',
  //   type: 'fill-extrusion', //设置当前图层类型 此为边
  //   source: 'roomData',
  //   layout: {
  //     visibility: 'visible' //是否显影
  //   },
  //   paint: {
  //     //设置属性
  //     'fill-extrusion-color': ['get', 'color'],
  //     'fill-extrusion-height': [
  //       'interpolate',
  //       ['linear'],
  //       ['zoom'],
  //       15,
  //       0,
  //       15.05,
  //       ['get', 'height']
  //     ],
  //     'fill-extrusion-base': [
  //       'interpolate',
  //       ['linear'],
  //       ['zoom'],
  //       15,
  //       0,
  //       15.05,
  //       ['get', 'min_height']
  //     ],
  //     'fill-extrusion-opacity': 0.6
  //   }
  // })

  // parameter.typeName = 'sqsf:outside_jianzhuwu'
  // const outbuildingData = await api
  //   .getLayerData('sqsf', parameter)
  //   .catch((err) => console.log(err))

  // map.addSource('outside_jianzhuwu', {
  //   type: 'geojson',
  //   data: outbuildingData
  // })
  // map.addLayer({
  //   id: 'outbuildings',
  //   type: 'fill-extrusion', //设置当前图层类型 此为边
  //   source: 'outside_jianzhuwu',
  //   layout: {
  //     visibility: 'visible' //是否显影
  //   },
  //   paint: {
  //     //设置属性
  //     'fill-extrusion-color': '#bfeeec',
  //     'fill-extrusion-height': [
  //       'interpolate',
  //       ['linear'],
  //       ['zoom'],
  //       15,
  //       0,
  //       15.05,
  //       ['get', 'height']
  //     ],
  //     'fill-extrusion-base': [
  //       'interpolate',
  //       ['linear'],
  //       ['zoom'],
  //       15,
  //       0,
  //       15.05,
  //       ['get', 'min_height']
  //     ],
  //     'fill-extrusion-opacity': 0.6
  //   }
  // })

  // map.loadImage('/images/lable/lable1.png', (error, image) => {
  //   if (error) {
  //     throw error
  //   }
  //   // Add the loaded image to the style's sprite with the ID 'kitten'.
  //   map.addImage('lable-1', image, {
  //     stretchX: [
  //       [28, 48],
  //       [86, 106]
  //     ],
  //     stretchY: [[15, 45]],
  //     content: [28, 15, 106, 45],
  //     pixelRatio: 2
  //   })
  //   map.addLayer({
  //     id: 'original',
  //     type: 'symbol',
  //     source: 'dlmc_point',
  //     layout: {
  //       'text-field': ['get', 'name'],
  //       'icon-image': 'lable-1',
  //       'icon-text-fit': 'both',
  //       'icon-allow-overlap': false,
  //       'text-allow-overlap': false,
  //       'text-size': 12
  //     },
  //     paint: {
  //       'text-color': 'rgb(54,153,255)'
  //     }
  //   })
  // })

  // parameter.typeName = 'sqsf:shumu'
  // const treeData = await api
  //   .getLayerData('sqsf', parameter)
  //   .catch((err) => console.log(err))

  // console.log('树木', treeData)
  // map.addSource('shumu', {
  //   type: 'geojson',
  //   data: treeData
  // })

  // map.addLayer({
  //   id: 'shumu',
  //   type: 'symbol',
  //   source: 'shumu',
  //   layout: {
  //     'icon-image': ['get', 'alias'],
  //     'icon-allow-overlap': false,
  //     'text-allow-overlap': false
  //   }
  // })

  // parameter.typeName = 'sqsf:jianzhuwulabel'
  // const buildingLabelData = await api
  //   .getData2(parameter)
  //   .catch((err) => console.log(err))

  // map.addSource('jianzhuwulabel', {
  //   type: 'geojson',
  //   data: buildingLabelData
  // })
  // map.addLayer({
  //   id: 'jianzhuwulabel',
  //   type: 'symbol',
  //   source: 'jianzhuwulabel',
  //   layout: {
  //     'text-field': ['get', 'name'],
  //     'text-size': 11,
  //     'text-letter-spacing': 0.2,
  //     'text-offset': [0, -1]
  //   },
  //   paint: {
  //     'text-color': '#181818',
  //     'text-halo-color': 'rgba(255, 255,255, 1)', // 光影效果
  //     'text-halo-width': 1.5 // 光影效果
  //   }
  // })

  // map.U.clickLayer('buildings', (e) => {
  //   removePopups()
  //   const name = e.features[0].properties.name
  //   // console.log('featureProperties', e);
  //   // const position2D = featureProperties.lonlatTwodim.split(',')

  //   if (name) {
  //     const popupHtml2D = '<div class="popup-simple">' + name + '</div>',
  //       popup = new mapboxgl.Popup({
  //         className: 'map-click-popup',
  //         maxWidth: '400px',
  //         closeButton: false,
  //         offset: [0, -15]
  //       }).setHTML(popupHtml2D)

  //     popup.setLngLat(e.lngLat).addTo(map)
  //     popups.push(popup)
  //   }
  //   e.preventDefault()
  // })
}

// 加载贴图建筑
async function addChartletLyer() {
  window.tb = new Threebox(map, map.getCanvas().getContext('webgl'), {
    defaultLights: true
  })
  const parameter = {
    service: 'WFS',
    version: '1.0.0',
    request: 'GetFeature',
    maxFeatures: '10000',
    outputFormat: 'application/json',
    typeName: 'zzdx:buildingkj'
  }
  const data = await api.getLayerData('zzdx', parameter).catch((err) => console.log(err))

  // molayersData = layerJson.data
  setTimeout(() => {
    addChartletLayer(data.features)
  }, 100)
}

function addChartletLayer(features) {
  map.addLayer({
    id: 'sqsfchartlet_layer',
    type: 'custom',
    renderingMode: '3d',
    onAdd: function (map, mbxContext) {
      addBuildings(features)
    },
    render: function (gl, matrix) {
      tb.update()
    }
  })
}

function addBuildings(data) {
  data.forEach((b) => {
    if (b.geometry) {
      if (b.geometry.coordinates) {
        // console.log('coordinates', b.geometry.coordinates)
        for (const coordinate of b.geometry.coordinates) {
          const polygon = turf.polygon([coordinate])
          const center = turf.centerOfMass(polygon).geometry.coordinates
          const texture = new THREE.TextureLoader().load(path + 'images/material/floors5.png')
          texture.wrapS = texture.wrapT = THREE.RepeatWrapping
          texture.repeat.set(1, parseInt(b.properties.height / 8)) //重复产生N个相同贴图 产生N行
          // texture.offset.set(0, 0.5)
          const material1 = new THREE.MeshBasicMaterial({
            // color: '#999999',
            transparent: true,
            opacity: 0.7,
            map: texture
          })
          material1.color.offsetHSL(0, 0.5, 0.5)
          const material = new THREE.MeshBasicMaterial({
            color: 'rgb(0,154,153)',
            transparent: true,
            opacity: 1
          })
          material.color.offsetHSL(0, 0.3, 0.3)
          const extrusion = tb.extrusion({
            coordinates: [coordinate],
            geometryOptions: { curveSegments: 1, bevelEnabled: false, depth: b.properties.height / 30 },
            materials: [material, material1]
          })
          // extrusion.addTooltip(b.properties.tooltip, true)
          extrusion.setCoords([center[0], center[1], 0])
          tb.add(extrusion)
        }
      }
    } else {
      console.log('coordinates', b)
    }
  })
}

function getView() {
  console.log('中心点', map.getCenter())
  console.log('倾斜角', map.getPitch())
  console.log('旋转角', map.getBearing())
  console.log('放大层级', map.getZoom().toFixed(1))
}

function changeSchool() {
  if (xiaoqu) {
    map.setCenter([102.71052463307672, 25.05258088822093])
  } else {
    map.setCenter([102.82799237023596, 24.847129783439215])
  }
  xiaoqu = !xiaoqu
}

function openFile() {
  exportGltf.value.click()
}

// 上传文件模型改变
const key = 'updatable'

function exportModel(file) {
  const f = file.target.files[0]

  if (f?.name.includes('.glb')) {
    loadPathModel(f)
    message.loading({ content: '模型上传中...', key })
  } else {
    message.error('请打开规定格式文件！')
  }
}

// 加载模型
function loadPathModel(fileInfo) {
  const name = fileInfo.name,
    dataURL = URL.createObjectURL(fileInfo),
    { lng, lat } = map.getCenter()
  console.log('信息', name, dataURL, lng, lat)
  const model = {
    name: name.split('.')[0],
    type: 'glb',
    zqobj: dataURL,
    obj: dataURL,
    units: 'meters',
    scale: 1,
    rotation: {
      x: 90,
      y: 0,
      z: 0
    },
    anchor: 'center',
    position: [lng, lat, 0]
  }

  window.tb.loadObj(model, function (mo) {
    const soldier = mo.setCoords(model.position)

    soldier.uuid = model.name
    soldier.traverse((e) => {
      if (e.material) {
        e.material.format = THREE.RGBAFormat
        if (model.belong === 'zdmodels.json') {
          e.material.color.offsetHSL(0, 0, -0.3)
          e.material.emissive = e.material.color
          e.material.emissiveMap = e.material.map
        }
      }
    })
    window.tb.add(soldier)
    message.success({ content: '上传成功!', key, duration: 2 })
  })
}

// 导出模型调整位置后的配置文件
function exportJsonFile() {
  console.log('导出文件', window.tb)
  const modelList = window.tb.scene.children[0].children,
    modelJson = {
      models: [],
      type: 'modelCollection',
      opacityZoom: 18
    }

  for (const modelObj of modelList) {
    const modelInfo = {
      name: modelObj.userData.name,
      type: modelObj.userData.type,
      obj: './model/' + modelObj.userData.name + '.glb',
      belong: modelObj.userData.belong,
      units: modelObj.userData.units,
      scale: modelObj.userData.scale,
      offsetHSL: modelObj.userData.offsetHSL || 0,
      campus: modelObj.userData.campus || '呈贡校区',
      rotation: modelObj.userData.rotation,
      anchor: modelObj.userData.anchor,
      position: modelObj.userData.position
    }

    modelInfo.position = modelObj.coordinates
    modelInfo.rotation.y =
          modelInfo.rotation.y +
          Number((modelObj.rotation.z * 180 / Math.PI).toFixed(0))
    // console.log("整理模型信息", modelInfo);
    modelJson.models.push(modelInfo)
  }
  console.log('模型json', modelJson)
  exportJson(modelJson, 'kmykdxmodels.json')
}

// 加载配置文件中图层信息
async function loadLayerJson() {
  const layerJson = await axios
    .get(path + 'config/kmykdxmodels4.11.json')
    .catch((err) => console.log(err))

  molayersData = layerJson.data
  setTimeout(() => {
    addModelLayer()
  }, 1000)
  // console.log("图层信息", layerJson);
}

// 根据配置信息加模型
async function addModelLayer() {
  // 设置模型编辑时旋转步数
  tb.rotationStep = 1
  map.addLayer({
    id: 'kmykcustom_layer',
    type: 'custom',
    renderingMode: '3d',
    onAdd: function (map, mbxContext) {
      for (const model of molayersData.models) {
        tb.loadObj(model, function (mo) {
          // console.log(mo);
          const soldier = mo.setCoords(model.position)

          soldier.uuid = model.name

          if (model.offsetHSL) {
            soldier.traverse((e) => {
              if (e.material) {
                // e.material.wireframe = true
                e.material.format = THREE.RGBAFormat
                e.material.color.offsetHSL(0, 0, model.offsetHSL)
                e.material.emissive = e.material.color
                e.material.emissiveMap = e.material.map
              }
            })
          } else {
            soldier.traverse((e) => {
              if (e.material) {
                e.material.format = THREE.RGBAFormat
              }
            })
          }
          tb.add(soldier)
        })
      }
    },
    render: function (gl, matrix) {
      tb.update()
    }
  })

}


</script>

<style lang='scss' scoped>
#mapbox-container {
  width: 100vw !important;
  height: 100vh !important;
}

.view-style {
  position: fixed;
  top: 50px;
  left: 50px;
  z-index: 10;
}
.style-name{
  position: fixed;
  top: 100px;
  left: 50px;
  z-index: 10;
  color: #eb9c8a;
}
</style>

